Help! This is Hard!

<-- Prev --------- Contents --------- Next -->

Hopefully by now, you've started looking at the WiiKart project, and you've been thinking about what needs to be done. If you're realizing that it's a little bit trickier than you'd expected, don't be discouraged... this isn't as straight-forward as it might have sounded! Let's walk through a couple of important points.

First, you should have noticed that there are 3 scenarios that we need to check for and handle separately:
  • The One button is being pressed
  • The Two button is being pressed
  • Neither the One nor the Two button are being pressed

The case where neither button is being pushed is easy. If no buttons are being pushed, then the robot should not be moving... so simply send motor commands to stop them!

The other two cases are considerably trickier- but very similar. Let's take a look at the first case, and we'll leave it to you to handle the second case.

If the One button is being pressed, then the car should move forward. But to complicate this, the wiimote might also be tilted, which means the car should be turning accordingly! That means that the left and right motors will likely have different values. If the left motor is moving faster than the right motor (assuming both motors are moving the car forward), then the robot will turn toward the right. Further, the higher the value of the left motor, the faster the robot will turn to the right. Naturally, the opposite applies to turning to the left. We can use this idea to calculate what power to set each of the motors to when the One button is pressed.

Suppose we have two variables:
int left_motor_power;
int right_motor_power;
What we need to do is calculate these two values based on the previously defined turn_percent variable. Recall that the turn_percent variable is between 0 and 1, and indicates how much the wiimote is tilted. So, we will use the turn_percent variable to decide how much to increase or decrease each of the two motors.

To simplify this, let's create a table that illustrates what we know about the motor values.
powtable1.jpg

What we want to do is populate this table to reflect our desired motor powers for each of the indicated turn_percent values. Remember that the turn_percent variable may have any value between 0 and 1 - not just 0, 0.5, and 1.0, but breaking it down into these "key points" will help us see what's going on.

Let's start with the simplest case- when turn_percent is 0.5. This means that the wiimote is NOT being tilted. In this case, the robot should go straight ahead. Let's say that we will set each motor to half power in this case. Recall that motor power goes from 0 to 28, with 14 indicating that the motor is not moving, and 0 and 28 indicating full counter-clockwise and clockwise, respectively. Also, note that because of the way we attached the motors to the squarebot, the wheels spin in opposite directions when both motors are set to clockwise... they are reversed! So, we will set the left motor to 21, and the right motor to 7 to make it go straight ahead. That will give each motor a magnitude of 7, but in opposite directions (one clockwise, one counter-clockwise. So the new table looks like this:

powtable2.jpg

Now, let's look at the other two cases. When turn_percent = 0.0, the user wants to make a complete right turn... which means we will be turning the magnitude of the left wheels up, and the magnitude of the right wheels down. How much we increase and decrease each motor will determine how the robot turns. Let's aim for the following behavior: when you are making a complete right turn, turn the right motor off, and the left motor to full power. This equates to setting the right motor to 14 (off), and the left motor to 28 (full clockwise). So our table looks like this:
powtable3.jpg

The final case is when turn_percent = 1.0, which is a complete left turn. Just like before, we define the following behavior: When you are making a complete left turn, turn the left motor off (14) ,and the right motor to full power (0). That completes our table.
powtable4.jpg

So... what if turn_percent is 0.7? For that sort of situation, we will have to interpolate. Interpolation is the process of estimating intermediate values based on a set of known points in a dataset. So, we use the values that we do know to estimate all of the values in between. How do we do that? Well, let's take a look at two graphs... The first graph shows a graph of the left motor values as we increase turn_percent. The second shows the same thing for the right motor:
power_graph1.jpg
Now, it might be a little more obvious where this is going. Let's go ahead and add some lines in there by fitting a straight line to those points:
power_graph2.jpg

Now, you can probably see that for any value of turn_percent between 0 and 1, we can figure out what the left and right motor values should be by looking at the lines on the graph... so how do we get numerical values out of that for our program? Well, to do that, we need to calculate the equation for those two lines.

Remember point-slope from math class? That's exactly what we need. The general equation for a line is y = m*x + b, where x and y are your coordinates, m is the slope of the line, and b is the y-intercept (where the line hits the y axis).

Let's look at the left motor line. The y-intercept is easy- we can see that the line hits the y axis at 28. To find the slope, we use the formula:
slope = (change in y) / (change in x)

For the left motor, the line drops from 28 to 14... so "change in y" is -14... and turn_percent goes from 0 to 1 during that time... so "change in x" is 1. That means slope = -14 / 1 = -14. Which means that the equation for the left motor value is y = -14*x + 28. Remember that in this case, the y value is the motor value, and the x value is the value of turn_percent.

We'll let you do the math to verify it, but the same process can be done for the right motor - the end result is that the right motor has the equation y = -14*x + 14.

So now what? Well now we can put these equations in our program! So suppose the user hits the One button. We have turn_percent, which is between 0 and 1, and we have equations to calculate the left and right motor values based on turn_percent. That's all we need! Below shows the calculations we should add.
int left_motor_power = -14.0 * turn_percent + 28.0;
int right_motor_power = -14.0 * turn_percent + 14.0;
Now there's one more thing that we need to fix. Notice that the left_motor_power and right_motor_power are int's... that means that they can't have decimal values. The values on the right are decimal values... which is bad. In order to fix this situation, we will need to cast the results of the right side of the equation as an integer. When you cast a value, you are telling the computer to treat it as one data type, even though it is technically another data type. Casting the right side as integers looks like this:
int left_motor_power = (int)(-14.0 * turn_percent + 28.0);
int right_motor_power = (int)(-14.0 * turn_percent + 14.0);
Keep in mind that if you cast a float (decimal) variable as an integer, the computer will chop off the decimal values- and you can't get them back. So, if the right side of the equation is equal to 8.7, cast it into an int will change it to 8... which is good enough for our purposes.

And that's it! The last thing is to send those values to the robot. The final result is the following if-statement.
if (wii_mote.WiimoteState.ButtonState.One)
{
   int left_motor_power = (int)(-14.0 * turn_percent + 28.0);
   int right_motor_power = (int)(-14.0 * turn_percent + 14.0);
   vc.SendMotorCommand(1, left_motor_power);
   vc.SendMotorCommand(2, right_motor_power);
}
The above code checks if the One button is being pushed. If it is, it calculates the left and right motor values, and sends them to the robot.

To finish the program, you should:
  • Add an else-if to the above if-statement, and check if the Two button is being pushed
  • If the Two button is being pushed, calculate the left and right motor values exactly like before (build the table, graph it, determine the equation for the lines, etc).
  • Add an else-block to the above if/else-if statement for the case where no buttons are being pushed... and in that case, turn both of the robot's motors off.

Go ahead and finish your robot! Just follow the steps we performed above, and you should have everything you need.


<-- Prev --------- Contents --------- Next -->